﻿using System;
using System.Collections.Generic;
using LogSystem;
using Pathfinding;
using UnityEngine;
using XLua;
using Yoozoo.Core.Extensions.Engine;
using Yoozoo.Gameplay.City.AI;
using Yoozoo.Gameplay.RTS;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
using UnityEngine.Rendering;

namespace Yoozoo.Gameplay.City
{
    public class CityRealAiWallManager : CityRealAiRoomManager
    {

        /// <summary>
        /// 巴士 实体资源加载器
        /// </summary>
        private ResLoader _resLoader;

        private KeyValuePair<GameObject, Animator>[] _busArray;

        private int _curBusIndex;

        private Action _getNewBusComplete;
        
        // npc 出城队列
        private Queue<CityAreaNpcController> _npcOutCityQueue;
        
        // npc 进城队列
        private Queue<CityAreaNpcController> _npcInCityQueue;

        // 正在上车的npc列表
        private List<int> _getOnTransportNpcUidList;

        // 巴士状态
        private CityRealWallState _wallState;

        // 阶段结束时间
        private float _stateEndTime;

        // npc上车计数
        private int _npcGetOnTransportIndex;

        // npc下车数量计数
        private int _npcGetOffTransportIndex;
        
        // npc 下车点
        public List<Vector3> GetOffTransportLocalPosList;
        
        // npc上车点
        public List<Vector3> GetOnTransportLocalPosList;

        // npc 上车间隔
        private int _npcGetOnTransportInterval = 0;

        // npc下车时间间隔
        private int _npcGetOffTransportInterval = 0;
        

        // 触发巴士立即进城的人数
        private int _triggerBusInCityNpcNum;

        // 巴士抵达后，一次下车进城的npc数量
        private int _maxNpcGetOffTransportNum;

        // 巴士出城后隐藏时间
        private float _busHideTime;

        // 巴士进城到下车点时间
        private float _busInCityGetOffTransportPointTime;
        
        // 巴士进城到上车点时间
        private float _busInCityGetOnTransportPointTime;

        // 巴士从下车点到上车点时间
        private float _busToGetOnTransportPointTime;

        // npc上车时间
        private float _npcGetOnTransportTime;

        // 巴士离城时间
        private float _busOutCityTime;
        
        // 是否暂停刷新
        private bool _isPaused = false;
        
        //============================开门营业的顾客巴士==================================
        // 巴士列表
        private List<CityRealAiCustomerBus> _customerBuses;
        // 检票员下次检票事件
        private List<float> _checkTicketTimestamps;
        
        // 下次自动营业的时刻
        private float _nextAutoCityBusinessTimestamp;
        
        // 下次巴士离开的间隔
        private float _nextBusLeaveTimestamp;
        
        
        //============================顾客、雇员投放==================================
        // 大门前的出生点
        private Vector3 _frontBirthPoint;
        
        // 后门的出生点
        private Vector3 _backBirthPoint;
        
        // 占领区域雇员生成点
        private List<List<Vector3>> _occupyAreaPointVecPosList;
        private List<List<Vector3>> _occupyAreaPointVecRotList;
        
        /// <summary>
        /// 前门等待点
        /// </summary>
        private List<Vector3> _frontStaffWaitPointPosList;
        private List<Vector3> _frontStaffWaitPointRotList;
        /// <summary>
        /// 前门等待点数据
        /// </summary>
        protected List<CityRealAiEventPointInfo> _frontStaffWaitPointInfoList;
        /// <summary>
        /// 前门等待点队列
        /// </summary>
        protected List<CityRealAiNpcController> _frontStaffWaitQueue;
        
        /// <summary>
        /// 后门等待点
        /// </summary>
        private List<Vector3> _backStaffWaitPointPosList;
        private List<Vector3> _backStaffWaitPointRotList;
        /// <summary>
        /// 后门等待点数据
        /// </summary>
        protected List<CityRealAiEventPointInfo> _backStaffWaitPointInfoList;
        /// <summary>
        /// 后门等待点队列
        /// </summary>
        protected List<CityRealAiNpcController> _backStaffWaitQueue;
        
        
        public CityRealAiWallManager(int containerId, int buildIndex, int areaId) : base(containerId, buildIndex, areaId)
        {
            _occupyAreaPointVecPosList = new List<List<Vector3>>();
            _occupyAreaPointVecRotList = new List<List<Vector3>>();
            _frontStaffWaitPointPosList = new List<Vector3>();
            _frontStaffWaitPointRotList = new List<Vector3>();
            _frontStaffWaitPointInfoList = new List<CityRealAiEventPointInfo>();
            _frontStaffWaitQueue = new List<CityRealAiNpcController>();
            _backStaffWaitPointPosList = new List<Vector3>();
            _backStaffWaitPointRotList = new List<Vector3>();
            _backStaffWaitPointInfoList = new List<CityRealAiEventPointInfo>();
            _backStaffWaitQueue = new List<CityRealAiNpcController>();
            
            _maxNpcGetOffTransportNum = _cfgMgr.GlobalCfg.incity_npc_ai_downcar_num_limit;
            _busHideTime = _cfgMgr.GlobalCfg.incity_npc_ai_bushidetime_num_limit;
            _busInCityGetOffTransportPointTime = _cfgMgr.GlobalCfg.incity_npc_ai_starttodownpoint_time;
            _busInCityGetOnTransportPointTime = _cfgMgr.GlobalCfg.incity_npc_ai_incity_time;
            _busToGetOnTransportPointTime = _cfgMgr.GlobalCfg.incity_npc_ai_downtouppoint_time;
            _npcGetOnTransportTime = _cfgMgr.GlobalCfg.incity_npc_ai_buswait_time_default;
            _busOutCityTime = _cfgMgr.GlobalCfg.incity_npc_ai_outcity_time;
            _triggerBusInCityNpcNum = _cfgMgr.GlobalCfg.incity_npc_ai_npcnum_buscallnow;
            _npcOutCityQueue = new Queue<CityAreaNpcController>();
            _npcInCityQueue = new Queue<CityAreaNpcController>();
            GetOffTransportLocalPosList = new List<Vector3>();
            GetOnTransportLocalPosList = new List<Vector3>();
            _busArray = new KeyValuePair<GameObject, Animator>[CityRealAiConst.BusNameArray.Length];
            _getOnTransportNpcUidList = new List<int>();
            _getNewBusComplete = GetNewBusComplete;
            _wallState = CityRealWallState.None;
            _resLoader = ResLoader.Alloc();
            _customerBuses = new List<CityRealAiCustomerBus>();
            for (int i = 0; i < CityRealAiCustomerBus.k_BusMaxCount; ++i)
            {
                _customerBuses.Add(new CityRealAiCustomerBus(i+1));
            }
            _checkTicketTimestamps = new List<float>();
            for (int i = 0; i < CityRealAiConst.TicketCollectorCount; ++i)
            {
                _checkTicketTimestamps.Add(0);
            }
            _nextBusLeaveTimestamp = Time.time;
            
            _nextAutoCityBusinessTimestamp = Time.time + CityRealAiConst.FirstAutoBusinessInterval;
        }

        public void AddGetOffTransportPoint(Vector3 getOffTransportPoint)
        {
            GetOffTransportLocalPosList.Add(getOffTransportPoint);
            AddMovePoint(getOffTransportPoint);
        }
        
        public void AddGetOnTransportPoint(Vector3 getOnTransportPoint)
        {
            GetOnTransportLocalPosList.Add(getOnTransportPoint);
            AddMovePoint(getOnTransportPoint);
        }
        
        public void SetupFrontBirthPoint(Vector3 frontBirthPoint)
        {
            _frontBirthPoint = frontBirthPoint;
            AddMovePoint(frontBirthPoint);
        }
        
        public void SetupBackBirthPoint(Vector3 backBirthPoint)
        {
            _backBirthPoint = backBirthPoint;
            AddMovePoint(backBirthPoint);
        }

        public void AddBusDownPoints()
        {
            // 初始化下车点位
            CityRealAiCustomerBus.InitBusDownPoints();

            foreach (Vector3 point in CityRealAiCustomerBus.k_BusDownPoints)
            {
                AddMovePoint(point);
            }
        }

        /// <summary>
        /// 获取下车点位置
        /// </summary>
        /// <param name="busIndex"></param>
        /// <returns></returns>
        public Vector3 GetBusDownPointWorldPos(int busIndex)
        {
            return CityRealAiCustomerBus.k_BusDownPoints[busIndex - 1];
        }
        
        public void AddOccupyAreaBirthPoint(int vecIndex, Vector3 waitPointPos, Vector3 waitPointRot)
        {
            if (vecIndex >= _occupyAreaPointVecPosList.Count)
            {
                _occupyAreaPointVecPosList.Add(new List<Vector3>());
                _occupyAreaPointVecRotList.Add(new List<Vector3>());
            }

            List<Vector3> posList = _occupyAreaPointVecPosList[vecIndex];
            List<Vector3> rotList = _occupyAreaPointVecRotList[vecIndex];
            posList.Add(waitPointPos);
            rotList.Add(waitPointRot);
            
            AddMovePoint(waitPointPos);
        }
        
        public void AddFrontStaffWaitPoint(Vector3 waitPointPos, Vector3 waitPointRot)
        {
            _frontStaffWaitPointPosList.Add(waitPointPos);
            _frontStaffWaitPointRotList.Add(waitPointRot);
            var waitPointInfo = new CityRealAiEventPointInfo();
            _frontStaffWaitPointInfoList.Add(waitPointInfo);
            AddMovePoint(waitPointPos);
        }
        
        public void AddBackStaffWaitPoint(Vector3 waitPointPos, Vector3 waitPointRot)
        {
            _backStaffWaitPointPosList.Add(waitPointPos);
            _backStaffWaitPointRotList.Add(waitPointRot);
            var waitPointInfo = new CityRealAiEventPointInfo();
            _backStaffWaitPointInfoList.Add(waitPointInfo);
            AddMovePoint(waitPointPos);
        }
        
        public Vector3 GetOccupyAreaBirthPointWorldPos(int areaId, int pointIndex)
        {
            // areaId、pointIndex从1开始
            areaId--;
            pointIndex--;
            
            Vector3 localPos;
            if (areaId > _occupyAreaPointVecPosList.Count || pointIndex >= _occupyAreaPointVecPosList[areaId].Count)
            {
                localPos = Vector3.zero;
            }
            else
            {
                localPos = _occupyAreaPointVecPosList[areaId][pointIndex];
            }
            return RoomRootTran.TransformPoint(localPos);
        }

        public Vector3 GetFrontBirthPointWorldPos()
        {
            return RoomRootTran.TransformPoint(_frontBirthPoint);
        }

        public Vector3 GetBackBirthPointWorldPos()
        {
            return RoomRootTran.TransformPoint(_backBirthPoint);
        }
        
        public bool TryStartBackStaffWaitQueue(CityRealAiNpcController npcCtrl, out int waitIndex, out int waitQueueIndex)
        {
            if (_backStaffWaitPointInfoList.Count <= 0) // 无排队点
            {
                waitIndex = -1;
                waitQueueIndex = -1;
                return false;
            }

            if (_backStaffWaitQueue.Count >= _backStaffWaitPointInfoList.Count) // 排队人数已满
            {
                waitIndex = -1;
                waitQueueIndex = -1;
                return false;
            }
            
            waitIndex = _backStaffWaitQueue.Count; // 占坑
            waitQueueIndex = -1;
            _backStaffWaitQueue.Add(npcCtrl);
            return true;
        }
        
        public void TriggerBackStaffWaitQueueLeave(CityRealAiNpcController npcCtrl)
        {
            List<CityRealAiNpcController> waitQueue = _backStaffWaitQueue;

            if (waitQueue!=null && waitQueue.Count>0)
            {
                waitQueue.Remove(npcCtrl);
            }
        }
        
        public CityRealAiEventPointInfo GetBackStaffWaitPointInfo(int index, int eventId)
        {
            // 单队列排队
            if (index < 0 || index >= _backStaffWaitPointInfoList.Count)
            {
                return null;
            }

            var waitInfo = _backStaffWaitPointInfoList[index];
            var pointCfg = new CityRealAiEventPointConfig();
            pointCfg.eventId = eventId;
            pointCfg.Position = _backStaffWaitPointPosList[index];
            pointCfg.Rotate = _backStaffWaitPointRotList[index];
            waitInfo.UpdatePointCfg(ref pointCfg);
            return waitInfo;
        }
        
        public bool TryStartFrontStaffWaitQueue(CityRealAiNpcController npcCtrl, out int waitIndex, out int waitQueueIndex)
        {
            if (_frontStaffWaitPointInfoList.Count <= 0) // 无排队点
            {
                waitIndex = -1;
                waitQueueIndex = -1;
                return false;
            }

            if (_frontStaffWaitQueue.Count >= _frontStaffWaitPointInfoList.Count) // 排队人数已满
            {
                waitIndex = -1;
                waitQueueIndex = -1;
                return false;
            }
            
            waitIndex = _frontStaffWaitQueue.Count; // 占坑
            waitQueueIndex = -1;
            _frontStaffWaitQueue.Add(npcCtrl);
            return true;
        }
        
        public void TriggerFrontStaffWaitQueueLeave(CityRealAiNpcController npcCtrl)
        {
            List<CityRealAiNpcController> waitQueue = _frontStaffWaitQueue;

            if (waitQueue!=null && waitQueue.Count>0)
            {
                waitQueue.Remove(npcCtrl);
            }
        }
        
        public CityRealAiEventPointInfo GetFrontStaffWaitPointInfo(int index, int eventId)
        {
            // 单队列排队
            if (index < 0 || index >= _frontStaffWaitPointInfoList.Count)
            {
                return null;
            }

            var waitInfo = _frontStaffWaitPointInfoList[index];
            var pointCfg = new CityRealAiEventPointConfig();
            pointCfg.eventId = eventId;
            pointCfg.Position = _frontStaffWaitPointPosList[index];
            pointCfg.Rotate = _frontStaffWaitPointRotList[index];
            waitInfo.UpdatePointCfg(ref pointCfg);
            return waitInfo;
        }
        
        /// <summary>
        /// 房间内是否满员
        /// </summary>
        public override bool IsFull
        {
            get
            {
                return false;
            }
        }
        
        public override void AddNpcCtrl(CityRealAiNpcController npcCtrl)
        {
            base.AddNpcCtrl(npcCtrl);
            if (npcCtrl is CityAreaNpcController areaNpcCtrl && npcCtrl.RoleClassType==(int)CityRealNpcClassType.Normal) // 只有区域npc才可以出城
            {
                if (_wallState == CityRealWallState.NpcGetOnTransport) // npc抵达时，巴士处于上车状态。
                {
                    if (Time.time >= _stateEndTime) // 已经过了上车时间，此时巴士正在等待未完成上车的npc，新来的npc不继续上车。
                    {
                        _npcOutCityQueue.Enqueue(areaNpcCtrl);
                        areaNpcCtrl.ExecuteGetOnTransportWaitQueue();
                    }
                    else // 直接上车
                    {
                        _npcInCityQueue.Enqueue(areaNpcCtrl);
                        _getOnTransportNpcUidList.Add(areaNpcCtrl.Uid);
                        areaNpcCtrl.ExecuteGetOnTransport(_npcGetOnTransportIndex);
                        _npcGetOnTransportIndex++;
                    }
                }
                else // 不在上车时间，执行排队事件。
                {
                    _npcOutCityQueue.Enqueue(areaNpcCtrl);
                    areaNpcCtrl.ExecuteGetOnTransportWaitQueue();
                    if (CityRealAiManager.GetInstance().UnlockBus && _npcOutCityQueue.Count == _triggerBusInCityNpcNum) // 达到呼叫巴士人数上限，则直接呼叫巴士
                    {
                        if (_wallState == CityRealWallState.BusHide)
                        {
                            _stateEndTime = Time.time;
                        }
                    }
                }
            }
        }

        public override CityRealAiNpcController RemoveNpcCtrl(int roleType, int uid)
        {
            var npcCtrl = base.RemoveNpcCtrl(roleType, uid);
            if (npcCtrl == null)
            {
                return null;
            }
            return npcCtrl;
        }

        public override void OnPause(bool isPause)
        {
            _isPaused = isPause;
            base.OnPause(isPause);
            foreach (var customerBus in _customerBuses)
            {
                customerBus.OnPause(isPause);
            }
            if (!isPause) // 取消暂停时，恢复巴士转换状态设置
            {
                switch (_wallState)
                {
                    case CityRealWallState.BusHide:
                        if (CityRealAiManager.GetInstance().UnlockBus)
                        {
                            if (_npcOutCityQueue.Count >= _triggerBusInCityNpcNum)
                            {
                                _stateEndTime = Time.time;
                            }
                            else
                            {
                                _stateEndTime = Time.time + _busHideTime;
                            }
                        }
                        else
                        {
                            _stateEndTime = Time.time + _busHideTime;
                        }
                        break;
                    case CityRealWallState.BusInCityGetOffTransportPoint:
                        _stateEndTime = Time.time + _busInCityGetOffTransportPointTime;
                        TriggerBusInCityAni();
                        break;
                    case CityRealWallState.NpcGetOffTransport:
                        var npcGetOffTransportNum = Mathf.Min(_npcInCityQueue.Count, (_maxNpcGetOffTransportNum - _npcGetOffTransportIndex));
                        _stateEndTime = Time.time + npcGetOffTransportNum * (CityRealAiConst.NpcGetOffTransportTime + 1);
                        _npcGetOffTransportInterval = CityRealAiConst.NpcGetOffTransportTime;
                        TriggerGetOffTransportBusWaitAni();
                        break;
                    case CityRealWallState.BusInCityGetOnTransportPoint:
                        _stateEndTime = Time.time + _busInCityGetOnTransportPointTime;
                        TriggerBusInCityAni();
                        break;
                    case CityRealWallState.BusToGetOnTransportPoint:
                        _stateEndTime = Time.time + _busToGetOnTransportPointTime;
                        TriggerGetOffTransportBusWaitAni();
                        TriggerBusToGetOnTransport();
                        break;
                    case CityRealWallState.NpcGetOnTransport:
                        _stateEndTime = Time.time + _npcGetOnTransportTime;
                        TriggerGetOnTransportBusWaitAni();
                        break;
                    case CityRealWallState.BusOutCity:
                        _stateEndTime = Time.time + _busOutCityTime;
                        TriggerBusOutCityAni();
                        break;
                }
            }
            
            // // 刷新自动营业时间
            // _nextAutoCityBusinessTimestamp = Time.time + CityRealAiConst.AutoBusinessInterval;
        }

        public override void OnUpdate()
        {
            base.OnUpdate();
            UpdateWallState();
            UpdateNpcGetOffTransport();
            UpdateNpcGetOnTransport();
            UpdateAutoCityBusiness();

            if (!_isPaused)
            {
                UpdateCustomerBuses();
                UpdateCheckTickets();
            }
        }

        private void UpdateWallState()
        {
            if (_wallState == CityRealWallState.None)
            {
                _stateEndTime = Time.time + _busHideTime;
                _wallState = CityRealWallState.BusHide;
            }
            else
            {
                if (Time.time >= _stateEndTime) // 切换状态
                {
                    ChangeWallState();
                }
            }
        }

        private void ChangeWallState()
        {
            switch (_wallState)
            {
                case CityRealWallState.BusHide: // 巴士隐藏时间结束，播放去往下车点或者上车点动画
                    if (CityRealAiManager.GetInstance().UnlockBus)
                    {
                        if (!CityRealAiManager.GetInstance().CityIsInNight && _npcInCityQueue.Count > 0) // 在白天，且有人可以下车，则先去下车点
                        {
                            _stateEndTime = Time.time + _busInCityGetOffTransportPointTime;
                            _wallState = CityRealWallState.BusInCityGetOffTransportPoint;
                        }
                        else
                        {
                            _stateEndTime = Time.time + _busInCityGetOnTransportPointTime;
                            _wallState = CityRealWallState.BusInCityGetOnTransportPoint;
                        }
                        TriggerBusInCityAni();
                    }
                    else // 巴士未解锁时，继续隐藏。
                    {
                        _stateEndTime = Time.time + _busHideTime;
                        _wallState = CityRealWallState.BusHide;
                    }
                    break;
                case CityRealWallState.BusInCityGetOffTransportPoint: // 巴士到达下车点动画结束，开始下车
                    var npcGetOffTransportNum = Mathf.Min(_npcInCityQueue.Count, _maxNpcGetOffTransportNum);
                    _stateEndTime = Time.time + npcGetOffTransportNum * (CityRealAiConst.NpcGetOffTransportTime + 1);
                    _npcGetOffTransportInterval = CityRealAiConst.NpcGetOffTransportTime;
                    _wallState = CityRealWallState.NpcGetOffTransport;
                    TriggerNpcGetOffTransport();
                    break;
                case CityRealWallState.NpcGetOffTransport: // npc下车结束，开始去往上车点，播放下车点到上车点动画
                    _stateEndTime = Time.time + _busToGetOnTransportPointTime;
                    _wallState = CityRealWallState.BusToGetOnTransportPoint;
                    TriggerBusToGetOnTransport();
                    break;
                case CityRealWallState.BusInCityGetOnTransportPoint: // 直达上车点动画播放完成，开始上车
                case CityRealWallState.BusToGetOnTransportPoint: // 下车点到上车点动画播放完成，开始上车
                    _stateEndTime = Time.time + _npcGetOnTransportTime;
                    _wallState = CityRealWallState.NpcGetOnTransport;
                    _npcGetOnTransportInterval = CityRealAiConst.NpcGetOnTransportTime;
                    TriggerNpcGetOnTransport();
                    break;
                case CityRealWallState.NpcGetOnTransport: // npc上车结束，播放去往隐藏点动画
                    if (_getOnTransportNpcUidList.Count > 0)
                    {
                        return;
                    }
                    _stateEndTime = Time.time + _busOutCityTime;
                    _wallState = CityRealWallState.BusOutCity;
                    TriggerBusOutCityAni();
                    break;
                case CityRealWallState.BusOutCity:
                    _stateEndTime = Time.time + _busHideTime;
                    _wallState = CityRealWallState.BusHide;
                    TriggerBusHide();
                    break;
            }
        }

        /// <summary>
        /// 巴士进城
        /// </summary>
        private void TriggerBusInCityAni()
        {
            GetNewBus(_getNewBusComplete);
        }

        private void GetNewBusComplete()
        {
            if (_busArray[_curBusIndex].Value != null)
            {
                if (_wallState == CityRealWallState.BusInCityGetOffTransportPoint)
                {
                    _busArray[_curBusIndex].Value.SetTrigger(CityRealAiConst.BusInCityGetOffTransportAniName);
                }
                else if (_wallState == CityRealWallState.BusInCityGetOnTransportPoint)
                {
                    _busArray[_curBusIndex].Value.SetTrigger(CityRealAiConst.BusInCityGetOnTransportAniName);
                }
            }
        }

        private void GetNewBus(Action complete)
        {
            _curBusIndex = Random.Range(0, _busArray.Length);
            if (_busArray[_curBusIndex].Key == null)
            {
                _resLoader.Add2Load(string.Format(CityRealAiConst.BusPath, CityRealAiConst.BusNameArray[_curBusIndex]), ((success, name, asset) =>
                {
                    if (success)
                    { 
                        var busGO = (GameObject)GameObject.Instantiate((Object)asset);
                        busGO.SetParent(RoomRootTran);
                        var busAni = busGO.GetComponentInChildren<Animator>();
                        _busArray[_curBusIndex] = new KeyValuePair<GameObject, Animator>(busGO, busAni);
                        complete?.Invoke();
                    }
                })).Load();
            }
            else
            {
                complete?.Invoke();
            }
        }

        /// <summary>
        /// npc下车，巴士等待
        /// </summary>
        private void TriggerNpcGetOffTransport()
        {
            TriggerGetOffTransportBusWaitAni();
            _npcGetOffTransportIndex = 0;
        }

        private void TriggerGetOffTransportBusWaitAni()
        {
            if (_busArray[_curBusIndex].Value != null)
            {
                _busArray[_curBusIndex].Value.SetTrigger(CityRealAiConst.BusGetOffTransportWaitAniName);
            }
        }

        private void TriggerBusToGetOnTransport()
        {
            if (_busArray[_curBusIndex].Value != null)
            {
                _busArray[_curBusIndex].Value.SetTrigger(CityRealAiConst.BusToGetOnTransportAniName);
            }
        }

        private void UpdateNpcGetOffTransport()
        {
            if (_wallState == CityRealWallState.NpcGetOffTransport)
            {
                if (_npcGetOffTransportIndex >= _maxNpcGetOffTransportNum)
                {
                    return;
                }
                if (_npcInCityQueue.Count > 0)
                {
                    if (_npcGetOffTransportInterval <= 0)
                    {
                        _npcGetOffTransportInterval = CityRealAiConst.NpcGetOffTransportTime;
                        var npcCtrl = _npcInCityQueue.Dequeue();
                        npcCtrl.ExecuteGetOffTransport(_npcGetOffTransportIndex);
                        _npcGetOffTransportIndex++;
                    }
                    else
                    {
                        _npcGetOffTransportInterval--;
                    }
                }
            }
        }

        /// <summary>
        /// npc上车
        /// </summary>
        private void TriggerNpcGetOnTransport()
        {
            _npcGetOnTransportIndex = 0;
            TriggerGetOnTransportBusWaitAni();
        }

        private void TriggerGetOnTransportBusWaitAni()
        {
            if (_busArray[_curBusIndex].Value != null)
            {
                _busArray[_curBusIndex].Value.SetTrigger(CityRealAiConst.BusWaitAniName);
            }
        }

        private void UpdateNpcGetOnTransport()
        {
            if (_wallState == CityRealWallState.NpcGetOnTransport)
            {
                if (Time.time >= _stateEndTime)
                {
                    return;
                }
                
                if (_npcOutCityQueue.Count > 0)
                {
                    if (_npcGetOnTransportInterval <= 0)
                    {
                        var npcCtrl = _npcOutCityQueue.Dequeue();
                        _npcInCityQueue.Enqueue(npcCtrl);
                        _getOnTransportNpcUidList.Add(npcCtrl.Uid);
                        npcCtrl.ExecuteGetOnTransport(_npcGetOnTransportIndex);
                        _npcGetOnTransportIndex++;
                    }
                    else
                    {
                        _npcGetOnTransportInterval--;
                    }
                }
            }
        }

        /// <summary>
        /// npc完成上车事件，取消标记
        /// </summary>
        /// <param name="areaNpcCtrl"></param>
        public void NpcGetOnTransportComplete(CityAreaNpcController areaNpcCtrl)
        {
            _getOnTransportNpcUidList.Remove(areaNpcCtrl.Uid);
        }

        /// <summary>
        /// 巴士出城
        /// </summary>
        private void TriggerBusOutCityAni()
        {
            if (_busArray[_curBusIndex].Value != null)
            {
                _busArray[_curBusIndex].Value.SetTrigger(CityRealAiConst.BusOutCityAniName);
            }
        }

        /// <summary>
        /// 巴士隐藏
        /// </summary>
        private void TriggerBusHide()
        {
            
        }

        public override void TriggerRoomStateChangeEvent(CityRealRoomStateChangeEvent changeEvent)
        {
            switch (changeEvent)
            {
                case CityRealRoomStateChangeEvent.StartUpgrade:
                {
                    if (IsInState(CityRealRoomState.Upgrade))
                    {
                        return;
                    }

                    SetupState(CityRealRoomState.Upgrade, true);
                    return;
                }

                case CityRealRoomStateChangeEvent.EndUpgrade:
                {
                    if (!IsInState(CityRealRoomState.Upgrade))
                    {
                        return;
                    }

                    SetupState(CityRealRoomState.Upgrade, false);
                    return;
                }
            }

            base.TriggerRoomStateChangeEvent(changeEvent);
        }
        
        public override void OnResetNpc()
        {
            _wallState = CityRealWallState.None;
            _npcOutCityQueue.Clear();
            _npcInCityQueue.Clear();
            _getOnTransportNpcUidList.Clear();
            foreach (var customerBus in _customerBuses)
            {
                customerBus.OnResetNpc();
            }
            base.OnResetNpc();
        }

        public override void Dispose()
        {
            _wallState = CityRealWallState.None;
            _npcOutCityQueue.Clear();
            _npcInCityQueue.Clear();
            for (int i = 0; i < _busArray.Length; i++)
            {
                if (_busArray[i].Key != null)
                {
                    Object.Destroy(_busArray[i].Key);
                }
            }
            Array.Clear(_busArray, 0, _busArray.Length);
            if (_resLoader != null)
            {
                _resLoader.Recycle2Cache();
                _resLoader = null;
            }
            base.Dispose();
        }
        
        // 开门营业
        public void OpenBusiness(LuaTable table)
        {
            LuaTable busList = table.Get<string, LuaTable>("busList");
            for (int i = 1; i <= busList.Length; ++i)
            {
                // 随机空闲巴士
                var bus = GetFreeCustomerBus();
                if (bus == null)
                {
                    Debug.LogError(LogModule.CityAI, "开门营业失败，没有找到空闲的巴士", LogLevelType.Develop);
                    return;
                }
                
                var busInfoTb = busList.Get<int, LuaTable>(i);

                LuaTable npcList = busInfoTb.Get<string, LuaTable>("npcList");
                var roleInfoList = new List<CityRealAiNpcInfo>(npcList.Length);
                for (int j = 1; j <= npcList.Length; ++j)
                {
                    var npcInfoTb = npcList.Get<int, LuaTable>(j);
                    var roleInfo = new CityRealAiNpcInfo();
                    roleInfo.cityRoleId = npcInfoTb.Get<string, int>("cityRoleId");
                    roleInfo.isNew = npcInfoTb.Get<string, bool>("newTag");
                    roleInfo.isSuperCustomer = npcInfoTb.Get<string, bool>("isSuperCustomer");
                    roleInfo.isShow = true;
                    roleInfo.buildingId = npcInfoTb.Get<string, int>("buildingId");
                    roleInfoList.Add(roleInfo);
                }

                // 巴士准备发车
                int readyDuration = busInfoTb.Get<string, int>("readyDuration");
                bus.ReadyIntoCity(RoomRootTran, CityBusinessType.Manual, readyDuration, roleInfoList);
            }
        }
        
        // 小人返回巴士
        public void CustomerBackToBus(int busIndex, CityAreaNpcController npcCtrl)
        {
            _customerBuses[busIndex-1].CustomerBackToBus(npcCtrl);
        }

        // 关闭营业
        public void CloseBusiness()
        {
            foreach (var customerBus in _customerBuses)
            {
                // 检测巴士是否属于手动营业
                if (customerBus.BusinessType == CityBusinessType.Manual &&
                    customerBus.BusState != CityRealCustomerBusState.None)
                {
                    customerBus.ReadyToLeaveCity();
                }
            }
        }
        
        // 恢复开门营业状态
        public void RestoreOpenBusiness(LuaTable table)
        {
            LuaTable busList = table.Get<string, LuaTable>("busList");
            for (int i = 1; i <= busList.Length; ++i)
            {
                // 随机空闲巴士
                var bus = GetFreeCustomerBus();
                if (bus == null)
                {
                    Debug.LogError(LogModule.CityAI, "恢复开门营业失败，没有找到空闲的巴士", LogLevelType.Develop);
                    return;
                }
                
                var busInfoTb = busList.Get<int, LuaTable>(i);

                LuaTable npcList = busInfoTb.Get<string, LuaTable>("npcList");
                var roleInfoList = new List<CityRealAiNpcInfo>(npcList.Length);
                for (int j = 1; j <= npcList.Length; ++j)
                {
                    var npcInfoTb = npcList.Get<int, LuaTable>(j);
                    var roleInfo = new CityRealAiNpcInfo();
                    roleInfo.cityRoleId = npcInfoTb.Get<string, int>("cityRoleId");
                    roleInfo.isShow = true;
                    roleInfo.buildingId = npcInfoTb.Get<string, int>("buildingId");
                    roleInfoList.Add(roleInfo);
                }

                // 巴士状态
                CityRealCustomerBusState busState = (CityRealCustomerBusState)busInfoTb.Get<string, int>("busState");

                switch (busState)
                {
                    case CityRealCustomerBusState.Parking:
                        {
                            // 巴士已停在车位上
                            bus.Parking(RoomRootTran, CityBusinessType.Manual, roleInfoList);
                        }
                        break;

                    default:
                        {
                            // 巴士准备发车
                            int readyDuration = busInfoTb.Get<string, int>("readyDuration");
                            bus.ReadyIntoCity(RoomRootTran, CityBusinessType.Manual, readyDuration, roleInfoList);
                        }
                        break;
                }
            }
        }

        // 自动营业
        public void OpenAutoBusiness(LuaTable table)
        {
            LuaTable busList = table.Get<string, LuaTable>("busList");
            for (int i = 1; i <= busList.Length; ++i)
            {
                // 随机空闲巴士
                var bus = GetAutoBusinessBus();
                if (bus == null)
                {
                    Debug.LogError(LogModule.CityAI, "自动营业失败，没有找到空闲的巴士", LogLevelType.Develop);
                    return;
                }
                
                var busInfoTb = busList.Get<int, LuaTable>(i);

                LuaTable npcList = busInfoTb.Get<string, LuaTable>("npcList");
                var roleInfoList = new List<CityRealAiNpcInfo>(npcList.Length);
                for (int j = 1; j <= npcList.Length; ++j)
                {
                    var npcInfoTb = npcList.Get<int, LuaTable>(j);
                    var roleInfo = new CityRealAiNpcInfo();
                    roleInfo.cityRoleId = npcInfoTb.Get<string, int>("cityRoleId");
                    roleInfo.isShow = true;
                    roleInfo.buildingId = npcInfoTb.Get<string, int>("buildingId");
                    roleInfoList.Add(roleInfo);
                }

                // 巴士状态
                CityRealCustomerBusState busState = (CityRealCustomerBusState)busInfoTb.Get<string, int>("busState");

                switch (busState)
                {
                    case CityRealCustomerBusState.Parking:
                        {
                            // 巴士已停在车位上
                            bus.Parking(RoomRootTran, CityBusinessType.Manual, roleInfoList, false);
                        }
                        break;
                }
            }
            return;
            
            // LuaTable busList = table.Get<string, LuaTable>("busList");
            // for (int i = 1; i <= busList.Length; ++i)
            // {
            //     if (GetUsedCustomerBusCount(CityBusinessType.Auto) >= CityRealAiCustomerBus.k_AutoCityBusinessMaxCount)
            //     {
            //         // 当前自动营业巴士已使用完
            //         return;
            //     }
            //     
            //     // 随机空闲巴士
            //     var bus = GetFreeCustomerBus();
            //     if (bus == null)
            //     {
            //         Debug.LogError(LogModule.CityAI, "自动营业失败，没有找到空闲的巴士", LogLevelType.Develop);
            //         return;
            //     }
            //     
            //     var busInfoTb = busList.Get<int, LuaTable>(i);
            //
            //     LuaTable npcList = busInfoTb.Get<string, LuaTable>("npcList");
            //     var roleInfoList = new List<CityRealAiNpcInfo>(npcList.Length);
            //     for (int j = 1; j <= npcList.Length; ++j)
            //     {
            //         var npcInfoTb = npcList.Get<int, LuaTable>(j);
            //         var roleInfo = new CityRealAiNpcInfo();
            //         roleInfo.isNew = npcInfoTb.Get<string, bool>("newTag");
            //         roleInfo.cityRoleId = npcInfoTb.Get<string, int>("cityRoleId");
            //         roleInfo.isShow = true;
            //         roleInfo.buildingId = npcInfoTb.Get<string, int>("buildingId");
            //         roleInfoList.Add(roleInfo);
            //     }
            //     
            //     // 巴士准备发车
            //     int readyDuration = 0;
            //     bus.ReadyIntoCity(RoomRootTran, CityBusinessType.Auto, readyDuration, roleInfoList);
            // }
        }

        public void NpcJumpToRoomNearby()
        {
            foreach (var bus in _customerBuses)
            {
                bus.NpcJumpToRoomNearby();
            }
        }
        
        // 关闭自动营业
        public void CloseAutoBusiness()
        {
            foreach (var customerBus in _customerBuses)
            {
                // 检测巴士是否属于手动营业
                if (customerBus.BusinessType == CityBusinessType.Auto &&
                    customerBus.BusState != CityRealCustomerBusState.None)
                {
                    customerBus.ReadyToLeaveCity();
                }
            }
        }
        
        // 清理所有营业巴士和小人
        public void ClearOpenBusiness()
        {
            foreach (var customerBus in _customerBuses)
            {
                // 检测巴士是否使用中
                if (customerBus.BusState != CityRealCustomerBusState.None)
                {
                    customerBus.ClearBus();
                }
            }
        }

        // 巴士离开间隔
        public float GetBusLeaveDelayTime()
        {
            if (Time.time >= _nextBusLeaveTimestamp)
            {
                _nextBusLeaveTimestamp = Time.time + CityRealAiConst.CustomerBusLeaveCityCD;
                return 0;
            }
            else
            {
                float delayTime = _nextBusLeaveTimestamp - Time.time;
                _nextBusLeaveTimestamp += CityRealAiConst.CustomerBusLeaveCityCD;
                return delayTime;
            }
        }

        // 刷新检票
        void UpdateCheckTickets()
        {
            for (int i = 0; i < CityRealAiConst.TicketCollectorCount; ++i)
            {
                // 获取排队的npc
                if (_multiWaitVecQueue.Count > i)
                {
                    var npcCtrlQueue = _multiWaitVecQueue[i];
                    if (npcCtrlQueue.Count <= 0)
                    {
                        continue;
                    }
                    
                    CityRealAiNpcController npcCtrl = npcCtrlQueue[0];
                    if (npcCtrl.TreeType == CityRealEventTreeType.WaitQueueEventTree && npcCtrl.Seeker.State == seekerState.executing)
                    {
                        // 检测当前检票口事件点是否被占用
                        int treeId = CityRealAiConst.CheckTicketEventTreeIds[i];
                        var eventTreeConfig = _cfgMgr.GetAiEventTreeConfig(treeId);
                        var eventInfo = eventTreeConfig.event_array[0];
                        var eventId = (int) eventInfo.x;
                        bool isCheckTicketPointEmpty = GetEventPointInfo(npcCtrl.Uid, eventId, CityRealEventPointState.Idle) != null;
                    
                        if (isCheckTicketPointEmpty)
                        {
                            // 触发检票
                            TriggerMultiWaitQueueMove(npcCtrl.WaitQueueIndex);
                            CityAreaNpcController areaNpc = npcCtrl as CityAreaNpcController;
                            areaNpc.TriggerCheckTicketEventTree(npcCtrl.WaitQueueIndex);
                            // 更新下次检票时间
                            _checkTicketTimestamps[i] = Time.time + CityRealAiConst.CheckTicketTime;
                        }
                    } 
                    
                }
            }
            
        }

        /// <summary>
        /// 获取固定的自动营业巴士
        /// </summary>
        /// <returns></returns>
        CityRealAiCustomerBus GetAutoBusinessBus()
        {
            if (this._customerBuses.Count > 0)
            {
                return this._customerBuses[CityRealAiConst.AutoBusinessBusIndex];
            }

            return null;
        }
        
        /// <summary>
        /// 随机一辆当前空闲的开门营业巴士
        /// </summary>
        CityRealAiCustomerBus GetFreeCustomerBus()
        {
            List<CityRealAiCustomerBus> freeBusList = ListPool<CityRealAiCustomerBus>.Get();
            foreach (var bus in _customerBuses)
            {
                if (bus.BusState == CityRealCustomerBusState.None)
                {
                    freeBusList.Add(bus);
                }
            }

            CityRealAiCustomerBus freeBus = null;
            if (freeBusList.Count > 0)
            {
                freeBus = freeBusList[UnityEngine.Random.Range(0, freeBusList.Count)];
            }
            ListPool<CityRealAiCustomerBus>.Release(freeBusList);

            return freeBus;
        }

        /// <summary>
        /// 根据营业类型获取当前使用中的巴士数量
        /// </summary>
        /// <returns></returns>
        int GetUsedCustomerBusCount(CityBusinessType businessType)
        {
            int freeCount = 0;
            foreach (var bus in _customerBuses)
            {
                if (bus.BusState!=CityRealCustomerBusState.None && bus.BusinessType==businessType)
                {
                    freeCount++;
                }
            }

            return freeCount;
        }
        
        // 刷新开门营业巴士
        void UpdateCustomerBuses()
        {
            // float deltaTime = Time.deltaTime;
            foreach (var bus in _customerBuses)
            {
                bus.OnUpdate(CityRealAiConst.UpdateDeltaTime);
            }
        }
        
        
        // 刷新自动营业
        void UpdateAutoCityBusiness()
        {
            if (_nextAutoCityBusinessTimestamp > 0 && Time.time >= _nextAutoCityBusinessTimestamp)
            {
                // // 通知上一次的顾客离开
                // CityRealAiCSharpCallLuaManager.CloseAutoBusiness();
                // 触发一次自动营业
                CityRealAiCSharpCallLuaManager.OpenAutoBusiness();
            
                _nextAutoCityBusinessTimestamp = Time.time + CityRealAiConst.AutoBusinessInterval;
            }
        }
        
    }
}